#!/usr/bin/python3

import os,json
import logging

class LocalUpgradeDataList:
    """
    Represent the (potentially partial) results of an unattended-upgrades
    run
    """
    POWEROFF_INSTALL_JSON = "/var/lib/kylin-system-updater/json/poweroff_install_meta.json"

    SHUTDOWN_INSTALL_DEFAULT = 0
    SHUTDOWN_INSTALL_FAILED = 1
    SHUTDOWN_INSTALL_SUCCESS = 2

    def __init__(self):
        self.will_upgrade_content = []

        #可升级的组列表
        self._push_groups = []
        self._push_steps = []
        self._push_singles = []
        self._pkgs_data = {}
        self._problem_resolver = {}

        #加版本号的升级包
        self.versoin_pkgs = {'single_upgrade':{}, 'groups_upgrade':{}}

        self.need_poweroff_install = False
        self.trigger_by_reboot = False
        self.auto_backup = True
        self.lack_of_space = False

        #任务队列 
        self.steps_queue = []
        self.last_task = ''
        self.finished_status = ''
        self.install_finished_status = self.SHUTDOWN_INSTALL_DEFAULT
        self.reboot_limity = 5
        self.resolver_name = "total_pkgs"
        
        if "en_US" in os.environ["LANG"]:
            self.lang = "en_US"
        else:
            self.lang = "zh_CN"

        if os.path.exists(self.POWEROFF_INSTALL_JSON):
            self.read_local()

    def refresh(self):
        #可升级的组列表
        self.will_upgrade_content = []
        self._push_groups = []
        self._push_steps = []
        self._push_singles = []

        self._pkgs_data = {}

        #加版本号的升级包
        self.versoin_pkgs = {'single_upgrade':{}, 'groups_upgrade':{}}

        self._problem_resolver = {}
        self.steps_queue = []
        self.lack_of_space = False
        self.last_task = ''
        self.need_poweroff_install = False
        self.trigger_by_reboot = False
        self.auto_backup = True

        self.finished_status = ''
        self.install_finished_status = self.SHUTDOWN_INSTALL_DEFAULT
        self.reboot_limity = 5

        self.resolver_name = "total_pkgs"

        if "en_US" in os.environ["LANG"]:
            self.lang = "en_US"
        else:
            self.lang = "zh_CN"
        logging.info("Refresh: Local Meta For System Update Successfully...")

    def refresh_and_write(self):
        self.refresh()
        self.write_local()

    def write_local(self):
        try:
            output_upgrade = {}
            output_upgrade.update({"_push_groups":self._push_groups})
            output_upgrade.update({"_push_steps":self._push_steps})
            output_upgrade.update({"steps_queue":self.steps_queue})
            output_upgrade.update({"_push_singles":self._push_singles})
            output_upgrade.update({"_pkgs_data":self._pkgs_data})
            output_upgrade.update({"versoin_pkgs":self.versoin_pkgs})
            output_upgrade.update({"_problem_resolver":self._problem_resolver})
            output_upgrade.update({"need_poweroff_install":self.need_poweroff_install})
            output_upgrade.update({"finished_status":self.finished_status})
            output_upgrade.update({"install_finished_status":self.install_finished_status})
            output_upgrade.update({"resolver_name":self.resolver_name})
            output_upgrade.update({"reboot_limity":self.reboot_limity})
            output_upgrade.update({"auto_backup":self.auto_backup})
            output_upgrade.update({"will_upgrade_content":self.will_upgrade_content})
            output_upgrade.update({"trigger_by_reboot":self.trigger_by_reboot})
            #6 产生JSON文件
            with open(self.POWEROFF_INSTALL_JSON, 'w', encoding='utf-8') as f:
                json.dump(output_upgrade, f, ensure_ascii=False, indent=4)

            logging.info("Generate Jsonfile(%s) to complete... ",self.POWEROFF_INSTALL_JSON)
            logging.info("Update Local Meta to json file in shutdown model...")
        except Exception as exc:
            logging.error(exc)

    def read_local(self):
        #读取组JSON文件
        try:
            with open(self.POWEROFF_INSTALL_JSON,'r') as f:
                data = json.load(f)

                self._push_groups = data["_push_groups"]
                self._push_steps = data["_push_steps"]
                self._push_singles = data["_push_singles"]
                self._pkgs_data = data["_pkgs_data"]
                self.steps_queue = data["steps_queue"]
                self.versoin_pkgs = data["versoin_pkgs"]
                self._problem_resolver = data["_problem_resolver"]
                self.need_poweroff_install = data["need_poweroff_install"]
                self.finished_status = data["finished_status"]
                self.resolver_name = data["resolver_name"]
                self.install_finished_status = data["install_finished_status"]
                self.reboot_limity = data["reboot_limity"]
                self.auto_backup = data["auto_backup"]
                self.will_upgrade_content = data["will_upgrade_content"]
                self.trigger_by_reboot = data["trigger_by_reboot"]
        except Exception as exc:
            logging.error(exc)

    #单包推送
    def add_singles(self,pkgs):
        self._push_singles = pkgs
    def get_singles(self):
        return self._push_singles
    
    #分步推送 添加分步数据
    def add_steps(self,groups,data):
        self._push_steps.append(groups)
        self._pkgs_data.update(data)

    def get_steps(self):
        return self._push_steps
    
    #组推送
    def add_groups(self,groups,data):
        self._push_groups.append(groups)
        self._pkgs_data.update(data)
    def get_groups(self):
        return self._push_groups

    #获取所以推送的升级
    def get_push(self):
        return self._push_groups + self._push_singles

    def is_steps(self,content):
        for cont in content:
            if cont in self._push_singles:
                return False
            
        if self._push_steps == []:
            return False
        else:
            return True

    def check_steps_reboot(self,content):
        return self._pkgs_data.get(content,{}).get('need_reboot',False)

    def get_steps_pkgs(self,step_name):
        pkgs_install = []
        pkgs_upgrade = []

        pkgs_install += self._pkgs_data.get(step_name,{}).get('install_list',[])
        pkgs_upgrade += self._pkgs_data.get(step_name,{}).get('upgrade_list',[]) 

        return pkgs_install,pkgs_upgrade 

    def get_push_pkgs(self,content):
        pkgs_install = []
        pkgs_upgrade = []

        if content == []:
            for group_name in self._push_groups:
                pkgs_install += self._pkgs_data.get(group_name,{}).get('pkgs_install',[])
                pkgs_upgrade += self._pkgs_data.get(group_name,{}).get('pkgs_upgrade',[]) 

            if self._push_singles != []:
                pkgs_upgrade += self._push_singles
        else:
            for cont in content:
                if cont in self._push_groups:
                    pkgs_install += self._pkgs_data.get(cont,{}).get('pkgs_install',[])
                    pkgs_upgrade += self._pkgs_data.get(cont,{}).get('pkgs_upgrade',[]) 

                if cont in self._push_singles:
                    pkgs_upgrade.append(cont)

        return pkgs_install,pkgs_upgrade

    #将要升级的内容
    def _make_upgrade_content(self,content):
        if content == []:
            return self._push_groups + self._push_singles
        else:
            return content

    def save_groups_resolver(self,pkgs_install,pkgs_upgrade,pkgs_remove,install_size):
        put_data = {self.resolver_name:{'install_pkgs':pkgs_install,'upgrade_pkgs':pkgs_upgrade,'reomve_pkgs':pkgs_remove,'install_size':install_size}}
        self._problem_resolver.update(put_data)

    def save_steps_resolver(self,step_name,pkgs_install,pkgs_upgrade,pkgs_remove):
        put_data = {step_name:{'install_pkgs':pkgs_install,'upgrade_pkgs':pkgs_upgrade,'reomve_pkgs':pkgs_remove}}
        self._problem_resolver.update(put_data)

    def reset_task_queue(self):
        self.steps_queue = []
        self._problem_resolver = {}

    def classify_content(self,content):
        if content == []:
            return self._push_singles,self._push_groups
        else:
            singles = []
            groups = []
            for cont in content:
                if cont in self._push_singles:
                    singles.append(cont)
                elif cont in self._push_groups:
                    groups.append(cont)
            return singles,groups

    def get_resolver_upgrade(self):
        pkgs_install = []
        pkgs_upgrade = []
        pkgs_remove = []
        pkgs_install = self._problem_resolver.get(self.resolver_name,{}).get('install_pkgs',[])
        pkgs_upgrade = self._problem_resolver.get(self.resolver_name,{}).get('upgrade_pkgs',[])
        pkgs_remove = self._problem_resolver.get(self.resolver_name,{}).get('reomve_pkgs',[])

        return pkgs_install,pkgs_upgrade,pkgs_remove

    def get_install_size(self):
        return self._problem_resolver.get(self.resolver_name,{}).get('install_size',0)

    def get_progress(self,content):
        #为了 解决获取包列表和获取进度传输的数据不能协同的问题
        if content == self.resolver_name:
            for groups in self._push_groups:
                content = groups
                break
        begin = self._pkgs_data.get(content,{}).get('progress_begin',0)
        end = self._pkgs_data.get(content,{}).get('progress_end',0)

        #当计算单包时 他们是没有进度的 补充进度
        if begin == 0 and end == 0:
            begin = 50
            end = 100

        return begin,end

    def push_pop(self,content):
        for cont in content:
            if cont in self._push_singles:
                self._push_singles.remove(cont)
            if cont in self._push_groups:
                self._push_groups.remove(cont)

    def get_resolver_steps(self,content):
        pkgs_install = []
        pkgs_upgrade = []
        pkgs_remove = []
        pkgs_install = self._problem_resolver.get(content,{}).get('install_pkgs',[])
        pkgs_upgrade = self._problem_resolver.get(content,{}).get('upgrade_pkgs',[])
        pkgs_remove = self._problem_resolver.get(content,{}).get('reomve_pkgs',[])

        return pkgs_install,pkgs_upgrade,pkgs_remove
    
    #升级完成后从升级列表删除
    def reset_push_content(self,content):
        for cont in content:
            if cont in self._push_singles:
                self._push_singles.remove(cont)
            if cont in self._push_groups:
                self._push_groups.remove(cont)

    def get_post_notify(self):
        notify = self._pkgs_data.get(self.last_task,{}).get("users_notify",{}).get("post_install_notify",None)
        if notify == None:
            return ''

        return notify.get(self.lang,'')

    def get_mid_notify(self,content):
        notify = self._pkgs_data.get(content,{}).get("users_notify",{}).get("mid_install_notify",None)
        if notify == None:
            return ''

        return notify.get(self.lang,'')

    def get_pre_script(self,content):
        script_list = []

        if content == self.resolver_name:
            for groups in self._push_groups:
                content = groups
                break

        script = self._pkgs_data.get(content,{}).get("script",None)
        if script == None:
            return script_list
        
        for scr in ["pre_update_status_check","pre_update_script"]:
            run_path = script.get(scr,[])

            if isinstance(run_path,list) == True:
                for sc in run_path:
                    if sc != '':
                        script_list.append(sc)
            elif isinstance(run_path,str) == True:
                if run_path != '':
                    script_list.append(run_path)
            else:
                pass

        return script_list

    def get_post_script(self,content):
        script_list = []
        if content == self.resolver_name:
            for groups in self._push_groups:
                content = groups
                break

        script = self._pkgs_data.get(content,{}).get("script",None)
        if script == None:
            return script_list
        
        for scr in ["post_update_status_check","post_update_script"]:
            run_path = script.get(scr,[])

            if isinstance(run_path,list) == True:
                for sc in run_path:
                    if sc != '':
                        script_list.append(sc)
            elif isinstance(run_path,str) == True:
                if run_path != '':
                    script_list.append(run_path)
            else:
                pass

        return script_list

    def check_install_required(self):
        if self.need_poweroff_install == True and self.steps_queue != [] \
                                        and self.will_upgrade_content != []:
                logging.info("Requires a Shutdown installtion...")
                return 1
        else:
            logging.info("Do not need to perform a shutdown installtion...")
            return 0